use std::collections::HashSet;

use swc_ecma_ast::*;  // 确保导入必要的AST类型
use swc_common::DUMMY_SP;
use swc_ecma_ast::{BinaryOp,
    BindingIdent, BlockStmt, ComputedPropName, Expr, ForHead, ForOfStmt, MemberExpr, MemberProp,
    Pat, Stmt, SwitchCase, SwitchStmt, VarDecl, VarDeclKind, VarDeclarator,
};
use swc_ecma_utils::{quote_ident, quote_str};
use std::collections::HashMap;
use crate::context::PropPos;
use crate::{
    common::field,
    context::Context,
    descriptor::{self, OneofDescriptorProto, field_descriptor_proto::Type,},
    runtime::lark::protobuf_js::codec::host_field_accessor,
};

use super::{
    codec::{self, field_accesscor, FieldAccessor},
    common::normalize_name,
    LarkPbRuntime,
};

impl LarkPbRuntime {
    pub(super) fn serialize_setup_inner(
        &self,
        ctx: &mut Context,
        descriptor: &descriptor::DescriptorProto,
        accessor: FieldAccessor,
    ) -> Vec<Stmt> {
        let mut stmts = vec![];
        stmts.push(self.serialize_setup_writer(ctx));
        // 跟踪处理过的 oneof 字段
        let mut oneofs = HashSet::new();
        // 源数据对象
        let host_expr = Expr::Ident(quote_ident!("$req"));

        for field in &descriptor.field {
             // 选择字段访问器（map 类型特殊处理）
            let field_accessor = if descriptor.options.map_entry() {
                accessor // 自定义访问器
            } else {
                host_field_accessor // 默认访问器
            };
            // 生成该字段的序列化代码
            let field_stmt = self.serialize_field_expr(//生成if语句中的内容
                ctx,
                host_expr.clone(),
                descriptor,
                field,
                field_accessor,
                &mut oneofs,
                None,
            );

            if let Some(stmt) = field_stmt {
                stmts.push(crate::if_stmt!(
                    // 检查字段是否有值
                    self.default_value_bin_expr( //构建if语句-判断条件-不包含内容
                        ctx,
                        host_expr.clone(),
                        descriptor,
                        field,
                        accessor
                    ),
                    Stmt::Block(BlockStmt {
                        span: DUMMY_SP,
                        stmts: vec![stmt]
                    })
                ));
            }
        }
        stmts.push(crate::return_stmt!(Expr::Ident(quote_ident!("$writer"))));
        stmts
    }

    pub(super) fn serialize_field_expr(
        &self,
        ctx: &mut Context,
        host_expr: Expr,
        descriptor: &descriptor::DescriptorProto,
        field: &descriptor::FieldDescriptorProto,
        field_accessor: FieldAccessor,
        oneofs: &mut HashSet<i32>,
        computed_prop: Option<bool>,
    ) -> Option<Stmt> {
        let has_computed_prop = computed_prop.unwrap_or(field.has_computed_prop());
        let field_accessor = if field.is_repeated() {
            codec::field_accesscor
        } else {
            field_accessor
        };
        let field_stmt: Stmt = if field.has_oneof_index() {
            eprintln!("[DEBUG] serialize.rs field >>>>>>>>>>>>>>>>>>>>>>>>>> ==== {:?}",field);
            if !oneofs.contains(&field.oneof_index()) {
                oneofs.insert(field.oneof_index());
                let oneof = descriptor
                    .oneof_decl
                    .get(field.oneof_index() as usize)
                    .unwrap();
                let mut fields = descriptor.get_oneof_fields(field);
                fields.push(field.clone());
                self.serialize_oneof_field_stmt(ctx, host_expr.clone(), oneof, &fields, descriptor)
            } else {
                return None;
            }
        } else if field.is_map(ctx) {
            self.serialize_map_field_stmt(ctx, host_expr.clone(), field)
        } else if field.is_message() {
            self.serialize_message_field_stmt(ctx, host_expr.clone(), field, field_accessor, computed_prop)
        } else {
            self.serialize_primitive_field_stmt(ctx, host_expr.clone(), field, field_accessor, None, computed_prop)
        };

        let field_stmt = if field.is_repeated() && !field.is_packed(ctx) && !field.is_map(ctx) {
            let field_name = normalize_name(field.name());
            
            // 获取基础类型名称
            let base_type = match field.nullish_type_annotation(ctx) {
                Some(type_ann) => {
                    // 提取基础类型名称
                    if let TsType::TsTypeRef(type_ref) = &*type_ann.type_ann {
                        if let TsEntityName::Ident(ident) = &type_ref.type_name {
                            ident.sym.clone()
                        } else {
                            "string".into() // 默认回退
                        }
                    } else {
                        "string".into() // 其他类型也回退到string
                    }
                },
                None => "string".into() // 没有类型注解时默认
            };
        
            // 构建 Array<string> 类型 (替代 string[])
            let array_type = TsType::TsTypeRef(TsTypeRef {
                span: DUMMY_SP,
                type_name: TsEntityName::Ident(Ident::new("Array".into(), DUMMY_SP)),
                type_params: Some(Box::new(TsTypeParamInstantiation {
                    span: DUMMY_SP,
                    params: vec![Box::new(TsType::TsTypeRef(TsTypeRef {
                        span: DUMMY_SP,
                        type_name: TsEntityName::Ident(Ident::new(base_type, DUMMY_SP)),
                        type_params: None,
                    }))],
                })),
            });
        
            // 变量声明部分
            let var_decl = Stmt::Decl(Decl::Var(Box::new(VarDecl {
                span: DUMMY_SP,
                kind: VarDeclKind::Let,
                decls: vec![VarDeclarator {
                    span: DUMMY_SP,
                    name: Pat::Ident(BindingIdent {
                        id: Ident::new(field_name.clone().into(), DUMMY_SP),
                        type_ann: None,
                    }),
                    init: Some(Box::new(Expr::TsAs(TsAsExpr {
                        span: DUMMY_SP,
                        expr: Box::new(host_field_accessor(host_expr.clone(), field, has_computed_prop)),
                        type_ann: Box::new(array_type),
                    }))),
                    definite: false,
                }],
                declare: false,
            })));

        
            // Create the writer expression that will go inside forEach
            let writer_expr = {
                // This should be your actual writer expression, for example:
                Expr::Call(CallExpr {
                    span: DUMMY_SP,
                    callee: Callee::Expr(Box::new(Expr::Member(MemberExpr {
                        span: DUMMY_SP,
                        obj: Box::new(Expr::Member(MemberExpr {
                            span: DUMMY_SP,
                            obj: Box::new(Expr::Ident(Ident::new("$writer".into(), DUMMY_SP))),
                            prop: MemberProp::Ident(Ident::new("uint32(50)".into(), DUMMY_SP)),
                        })),
                        prop: MemberProp::Ident(Ident::new("string".into(), DUMMY_SP)),
                    }))),
                    args: vec![ExprOrSpread {
                        spread: None,
                        expr: Box::new(Expr::Ident(Ident::new("tag".into(), DUMMY_SP))),
                    }],
                    type_args: None,
                })
            };
        
            // forEach call
            let for_each = Stmt::Expr(ExprStmt {
                span: DUMMY_SP,
                expr: Box::new(Expr::Call(CallExpr {
                    span: DUMMY_SP,
                    callee: Callee::Expr(Box::new(Expr::Member(MemberExpr {
                        span: DUMMY_SP,
                        obj: Box::new(Expr::Ident(Ident::new(field_name.into(), DUMMY_SP))),
                        prop: MemberProp::Ident(Ident::new("forEach".into(), DUMMY_SP)),
                    }))),
                    args: vec![ExprOrSpread {
                        spread: None,
                        expr: Box::new(Expr::Arrow(ArrowExpr {
                            span: DUMMY_SP,
                            params: vec![Pat::Ident(BindingIdent {
                                id: Ident::new("tag".into(), DUMMY_SP),
                                type_ann: None,
                            })],
                            body: Box::new(BlockStmtOrExpr::Expr(Box::new(writer_expr))),
                            is_async: false,
                            is_generator: false,
                            type_params: None,
                            return_type: None,
                        })),
                    }],
                    type_args: None,
                })),
            });
        
            // Combine both statements
            Stmt::Block(BlockStmt {
                span: DUMMY_SP,
                stmts: vec![var_decl, for_each],
            })
        } else {
            field_stmt
        };
        Some(field_stmt)
    }
    

    pub(super) fn serialize_setup_writer(&self, ctx: &mut Context) -> Stmt {
        let writer = ctx.get_import_from(Self::RUNTIME_PACKAGE, Self::PB_WRITER_NAME);
        let call = Expr::Member(MemberExpr {
            span: DUMMY_SP,
            obj: Box::new(writer.into()),
            prop: MemberProp::Ident(quote_ident!("create")),
        });
        let w = Expr::Ident(quote_ident!("$w"));
        let writer_decl_init = crate::bin_expr!(
            w,
            crate::call_expr!(call),
            swc_ecma_ast::BinaryOp::NullishCoalescing
        );
        
        Stmt::Decl(Decl::Var(Box::new(VarDecl {
            span: DUMMY_SP,
            kind: VarDeclKind::Const,
            declare: false,
            decls: vec![VarDeclarator {
                span: DUMMY_SP,
                name: Pat::Ident(BindingIdent {
                    id: quote_ident!("$writer"),
                    type_ann: Some(Box::new(TsTypeAnn {
                        span: DUMMY_SP,
                        type_ann: Box::new(TsType::TsTypeRef(TsTypeRef {
                            span: DUMMY_SP,
                            type_name: TsEntityName::Ident(quote_ident!("Writer")),
                            type_params: None,
                        })),
                    })),
                }),
                init: Some(Box::new(writer_decl_init)),
                definite: false,
            }],
        })))
    }


    pub fn serialize_oneof_field_stmt(
        &self,
        ctx: &mut Context,
        host_expr: Expr,
        oneof: &OneofDescriptorProto,
        fields: &[descriptor::FieldDescriptorProto],
        descriptor: &descriptor::DescriptorProto,
    ) -> Stmt {
        
        //获取联合类型
        let union_class_name = self.oneof_type_name(oneof, PropPos::Interface);
        // 生成 let identityParam: IIdentity = $req.identity as IIdentity
        let identity_decl = Stmt::Decl(Decl::Var(Box::new(VarDecl {
            span: DUMMY_SP,
            kind: VarDeclKind::Let,
            decls: vec![VarDeclarator {
                span: DUMMY_SP,
                name: Pat::Ident(BindingIdent {
                    id: Ident::new("oneOfParam".into(), DUMMY_SP),
                    type_ann: Some(Box::new(TsTypeAnn {
                        span: DUMMY_SP,
                        type_ann: Box::new(TsType::TsTypeRef(TsTypeRef {
                            span: DUMMY_SP,
                            type_name: TsEntityName::Ident(union_class_name.clone()),
                            type_params: None,
                        })),
                    })),
                }),
                init: Some(Box::new(Expr::TsAs(TsAsExpr {
                    span: DUMMY_SP,
                    expr: Box::new(Expr::Member(MemberExpr {
                        span: DUMMY_SP,
                        obj: Box::new(Expr::Ident(Ident::new("$req".into(), DUMMY_SP))),
                        prop: MemberProp::Ident(Ident::new("identity".into(), DUMMY_SP)),
                    })),
                    type_ann: Box::new(TsType::TsTypeRef(TsTypeRef {
                        span: DUMMY_SP,
                        type_name: TsEntityName::Ident(union_class_name.clone()),
                        type_params: None,
                    })),
                }))),
                definite: false,
            }],
            declare: false,
        })));
    
        // 生成 let kind: string = identityParam.$oneofKind
        let kind_decl = Stmt::Decl(Decl::Var(Box::new(VarDecl {
            span: DUMMY_SP,
            kind: VarDeclKind::Let,
            decls: vec![VarDeclarator {
                span: DUMMY_SP,
                name: Pat::Ident(BindingIdent {
                    id: Ident::new("kind".into(), DUMMY_SP),
                    type_ann: Some(Box::new(TsTypeAnn {
                        span: DUMMY_SP,
                        type_ann: Box::new(TsType::TsKeywordType(TsKeywordType {
                            span: DUMMY_SP,
                            kind: TsKeywordTypeKind::TsStringKeyword,
                        })),
                    })),
                }),
                init: Some(Box::new(Expr::Member(MemberExpr {
                    span: DUMMY_SP,
                    obj: Box::new(Expr::Ident(Ident::new("oneOfParam".into(), DUMMY_SP))),
                    prop: MemberProp::Ident(Ident::new("$oneofKind".into(), DUMMY_SP)),
                }))),
                definite: false,
            }],
            declare: false,
        })));
    
        // 生成 switch 语句的各个 case
        let mut cases = vec![];
        for field in fields {
            let type_name = self.oneof_variant_type_name(oneof, field, PropPos::Interface);
            let field_name = normalize_name(field.name());

            let var_name = format!("{}Identity", field_name.clone());
            let field_expr = Expr::Ident(Ident {
                span: DUMMY_SP,       // 使用默认的源码位置
                sym: var_name.clone().into(),  // 将字符串转换为标识符名称
                optional: false,       // 不是可选标识符(如 foo?.bar)
            });
            // 生成 let varName: Type = identityParam as Type
            let var_decl = Stmt::Decl(Decl::Var(Box::new(VarDecl {
                span: DUMMY_SP,
                kind: VarDeclKind::Let,
                decls: vec![VarDeclarator {
                    span: DUMMY_SP,
                    name: Pat::Ident(BindingIdent {
                        id: Ident::new(var_name.clone().into(), DUMMY_SP),
                        type_ann: Some(Box::new(TsTypeAnn {
                            span: DUMMY_SP,
                            type_ann: Box::new(TsType::TsTypeRef(TsTypeRef {
                                span: DUMMY_SP,
                                type_name: TsEntityName::Ident(type_name.clone()),
                                type_params: None,
                            })),
                        })),
                    }),
                    init: Some(Box::new(Expr::TsAs(TsAsExpr {
                        span: DUMMY_SP,
                        expr: Box::new(Expr::Ident(Ident::new("oneOfParam".into(), DUMMY_SP))),
                        type_ann: Box::new(TsType::TsTypeRef(TsTypeRef {
                            span: DUMMY_SP,
                            type_name: TsEntityName::Ident(type_name.clone()),
                            type_params: None,
                        })),
                    }))),
                    definite: false,
                }],
                declare: false,
            })));
    
            // 生成 if (varName.field) { writer.uint32(tag).type_(varName.field); }
            // let write_expr = if field.is_message() {
            //     // 处理消息类型字段
            //     self.serialize_message_field_stmt(
            //         ctx,
            //         Expr::Ident(Ident::new(var_name.clone().into(), DUMMY_SP)),
            //         field,
            //         |e| {
            //             // 字段访问器
            //             Expr::Member(MemberExpr {
            //                 span: DUMMY_SP,
            //                 obj: Box::new(e),
            //                 prop: MemberProp::Ident(Ident::new(field_name.into(), DUMMY_SP)),
            //             })
            //         },
            //         Some(false),
            //     )
            // } else {
            //     // 处理基本类型字段 (保留原始链式调用风格)
            //     let method_name = match field.type_() {
            //         Type::TYPE_STRING => "string_",
            //         Type::TYPE_INT32 => "int32",
            //         Type::TYPE_BOOL => "bool",
            //         _ => "string_",
            //     };
    
            //     Stmt::Expr(ExprStmt {
            //         span: DUMMY_SP,
            //         expr: Box::new(Expr::Call(CallExpr {
            //             span: DUMMY_SP,
            //             callee: Callee::Expr(Box::new(Expr::Member(MemberExpr {
            //                 span: DUMMY_SP,
            //                 obj: Box::new(Expr::Call(CallExpr {
            //                     span: DUMMY_SP,
            //                     callee: Callee::Expr(Box::new(Expr::Member(MemberExpr {
            //                         span: DUMMY_SP,
            //                         obj: Box::new(Expr::Ident(Ident::new("$writer".into(), DUMMY_SP))),
            //                         prop: MemberProp::Ident(Ident::new("uint32".into(), DUMMY_SP)),
            //                     }))),
            //                     args: vec![ExprOrSpread {
            //                         spread: None,
            //                         expr: Box::new(Expr::Lit(Lit::Num(Number {
            //                             span: DUMMY_SP,
            //                             value: field.number() as f64,
            //                             raw: None,
            //                         }))),
            //                     }],
            //                     type_args: None,
            //                 })),
            //                 prop: MemberProp::Ident(Ident::new(method_name.into(), DUMMY_SP)),
            //             }))),
            //             args: vec![ExprOrSpread {
            //                 spread: None,
            //                 expr: Box::new(Expr::Member(MemberExpr {
            //                     span: DUMMY_SP,
            //                     obj: Box::new(Expr::Ident(Ident::new(var_name.into(), DUMMY_SP))),
            //                     prop: MemberProp::Ident(Ident::new(field_name.into(), DUMMY_SP)),
            //                 })),
            //             }],
            //             type_args: None,
            //         })),
            //     })
            // };
            let write_expr = if field.is_message() {
                self.serialize_message_field_stmt(
                    ctx,
                    field_expr.clone(),
                    field,
                    host_field_accessor,
                    Some(false),
                )
            } else {
                self.serialize_oneof_primitive_field_stmt(
                    ctx,
                    field_expr.clone(),
                    field,
                    host_field_accessor,
                    None,
                    Some(false),
                )
            };
       
            let write_stmt = Stmt::If(IfStmt {
                span: DUMMY_SP,
                test: Box::new(Expr::Member(MemberExpr {
                    span: DUMMY_SP,
                    obj: Box::new(Expr::Ident(Ident::new(var_name.clone().into(), DUMMY_SP))),
                    prop: MemberProp::Ident(Ident::new(field_name.clone().into(), DUMMY_SP)),
                })),
                cons: Box::new(Stmt::Block(BlockStmt {
                    span: DUMMY_SP,
                    stmts: vec![write_expr],
                })),
                alt: None,
            });
    
            cases.push(SwitchCase {
                span: DUMMY_SP,
                test: Some(Box::new(Expr::Lit(Lit::Str(Str {
                    span: DUMMY_SP,
                    value: field_name.clone().into(),
                    raw: None,
                })))),
                cons: vec![var_decl, write_stmt, Stmt::Break(BreakStmt {
                    span: DUMMY_SP,
                    label: None,
                })],
            });
        }
    
        // 组合完整的 switch 语句
        let switch_stmt = Stmt::Switch(SwitchStmt {
            span: DUMMY_SP,
            discriminant: Box::new(Expr::Ident(Ident::new("kind".into(), DUMMY_SP))),
            cases,
        });
    
        // 返回组合后的语句块
        Stmt::Block(BlockStmt {
            span: DUMMY_SP,
            stmts: vec![identity_decl, kind_decl, switch_stmt],
        })
    }
    // pub(super) fn serialize_oneof_field_stmt(
    //     &self,
    //     ctx: &mut Context,
    //     host: Expr,
    //     oneof: &OneofDescriptorProto,
    //     oneofs: &[descriptor::FieldDescriptorProto],
    // ) -> Stmt {
    //     // req.oneof_field_name
    //     let field_expr = crate::member_expr_bare!(host, normalize_name(oneof.name()));
    //     let cases: Vec<SwitchCase> = oneofs
    //         .iter()
    //         .map(|o| {
    //             let write_expr = if o.is_message() {
    //                 self.serialize_message_field_stmt(
    //                     ctx,
    //                     field_expr.clone(),
    //                     o,
    //                     host_field_accessor,
    //                     Some(false),
    //                 )
    //             } else {
    //                 self.serialize_primitive_field_stmt(
    //                     ctx,
    //                     field_expr.clone(),
    //                     o,
    //                     host_field_accessor,
    //                     None,
    //                     Some(false),
    //                 )
    //             };
    //             let stmts = vec![
    //                 write_expr,
    //                 Stmt::Break(swc_ecma_ast::BreakStmt {
    //                     span: DUMMY_SP,
    //                     label: None,
    //                 }),
    //             ];
    //             SwitchCase {
    //                 span: DUMMY_SP,
    //                 test: Some(Box::new(crate::lit_str!(normalize_name(o.name())).into())),
    //                 cons: stmts,
    //             }
    //         })
    //         .collect();
    //     assert!(
    //         !cases.is_empty(),
    //         "no variant for oneof: {}.{}",
    //         ctx.get_namespace(),
    //         oneof.name()
    //     );

    //     Stmt::Switch(SwitchStmt {
    //         span: DUMMY_SP,
    //         discriminant: Box::new(crate::member_expr_bare!(field_expr.clone(), "$oneofKind")),
    //         cases,
    //     })
    // }

    pub fn serialize_message_field_stmt(
        &self,
        ctx: &mut Context,
        host: Expr,
        field: &descriptor::FieldDescriptorProto,
        field_accessor: FieldAccessor,
        computed_prop: Option<bool>,
    ) -> Stmt {
        let has_computed_prop = computed_prop.unwrap_or(field.has_computed_prop());
        let access_expr = field_accessor(host, field, has_computed_prop);
         // If we need a type assertion, we'll wrap the expression in a TSAsExpr
        let access_expr = if !field.type_name().is_empty() {
            let type_name = ctx.lazy_type_ref(field.type_name());
            Expr::TsAs(swc_ecma_ast::TsAsExpr {
                expr: Box::new(access_expr),
                type_ann: Box::new(TsType::TsTypeRef(TsTypeRef {
                    span: Default::default(),
                    type_name: TsEntityName::Ident(type_name),
                    type_params: None,
                })),
                span: Default::default(),
            })
        } else {
            access_expr
        };
        let full_name = ctx.lazy_type_ref(field.type_name());
        // $w.uint32(/* (id << 3) |  wireType */)
        let id_write_expr = crate::call_expr!(
            crate::member_expr!("$writer", "uint32_"),
            vec![crate::expr_or_spread!(
                crate::lit_num!(field.field_header().value()).into()
            )]
        );
        let writer_fork_expr = crate::call_expr!(crate::member_expr_bare!(id_write_expr, "fork"));
        let field_write_expr = crate::call_expr!(
            crate::member_expr!(full_name, "encode"),
            vec![
                crate::expr_or_spread!(access_expr),
                crate::expr_or_spread!(writer_fork_expr)
            ]
        );
        // package.XXX.encode(req.field_name, $w.uint32(/* */).fork()).ldelim();
        crate::expr_stmt!(crate::call_expr!(crate::member_expr_bare!(
            field_write_expr,
            "ldelim_"
        )))
    }

    pub fn serialize_map_field_stmt(
        &self,
        ctx: &mut Context,
        host: Expr,
        field: &descriptor::FieldDescriptorProto,
    ) -> Stmt {
        let descriptor = ctx
            .get_map_type(field.type_name())
            .unwrap_or_else(|| panic!("cannot find the map type {}", field.type_name()));
    
        let field_name = normalize_name(field.name());
        let record_ident = format!("{}Record", field_name);
        let record_ident = quote_ident!(record_ident);
        let entry_ident = quote_ident!(field_name);
    
        // 生成 if 语句块
        let if_block = BlockStmt {
            span: DUMMY_SP,
            stmts: vec![
                // let scoresedRecord = ($req.scoresed as Record<string, number>)
                Stmt::Decl(Decl::Var(Box::new(VarDecl {
                    span: DUMMY_SP,
                    kind: VarDeclKind::Let,
                    decls: vec![VarDeclarator {
                        span: DUMMY_SP,
                        name: Pat::Ident(record_ident.clone().into()),
                        init: Some(Box::new(Expr::Paren(ParenExpr {
                            span: DUMMY_SP,
                            expr: Box::new(Expr::TsAs(TsAsExpr {
                                span: DUMMY_SP,
                                expr: Box::new(Expr::Paren(ParenExpr {
                                    span: DUMMY_SP,
                                    expr: Box::new(Expr::Member(MemberExpr {
                                        span: DUMMY_SP,
                                        obj: Box::new(host.clone()),
                                        prop: MemberProp::Ident(entry_ident.clone()),
                                    })),
                                })),
                                type_ann: Box::new(TsType::TsTypeRef(TsTypeRef {
                                    span: DUMMY_SP,
                                    type_name: TsEntityName::Ident(Ident::new("Record".into(), DUMMY_SP)),
                                    type_params: Some(Box::new(TsTypeParamInstantiation {
                                        span: DUMMY_SP,
                                        params: vec![Box::new(  
                                        TsType::TsKeywordType(TsKeywordType {
                                            span: DUMMY_SP,
                                            kind: TsKeywordTypeKind::TsStringKeyword,
                                        })),
                                        Box::new( 
                                        TsType::TsKeywordType(TsKeywordType {
                                            span: DUMMY_SP,
                                            kind: TsKeywordTypeKind::TsNumberKeyword,
                                        })),
                                         
                                        ],
                                    })),
                                })),
                            })),
                        }))),
                        definite: false,
                    }],
                    declare: false,
                }))),
                // scoresedRecord.forEach(...)
                Stmt::Expr(ExprStmt {
                    span: DUMMY_SP,
                    expr: Box::new(Expr::Call(CallExpr {
                        span: DUMMY_SP,
                        callee: Callee::Expr(Box::new(Expr::Member(MemberExpr {
                            span: DUMMY_SP,
                            obj: Box::new(Expr::Ident(record_ident.clone())),
                            prop: MemberProp::Ident(quote_ident!("forEach")),
                        }))),
                        args: vec![ExprOrSpread {
                            spread: None,
                            expr: Box::new(Expr::Arrow(ArrowExpr {
                                span: DUMMY_SP,
                                params: vec![
                                    Pat::Ident(quote_ident!("value").into()),
                                    Pat::Ident(quote_ident!("key").into()),
                                ],
                                body: Box::new(BlockStmtOrExpr::BlockStmt(BlockStmt {
                                    span: DUMMY_SP,
                                    stmts: vec![
                                        // ($writer.uint32(58)).fork()
                                        Stmt::Expr(ExprStmt {
                                            span: DUMMY_SP,
                                            expr: Box::new(Expr::Call(CallExpr {
                                                span: DUMMY_SP,
                                                callee: Callee::Expr(Box::new(Expr::Member(MemberExpr {
                                                    span: DUMMY_SP,
                                                    obj: Box::new(Expr::Paren(ParenExpr {
                                                        span: DUMMY_SP,
                                                        expr: Box::new(Expr::Call(CallExpr {
                                                            span: DUMMY_SP,
                                                            callee: Callee::Expr(Box::new(Expr::Member(MemberExpr {
                                                                span: DUMMY_SP,
                                                                obj: Box::new(Expr::Ident(quote_ident!("$writer"))),
                                                                prop: MemberProp::Ident(quote_ident!("uint32")),
                                                            }))),
                                                            args: vec![ExprOrSpread {
                                                                spread: None,
                                                                expr: Box::new(Expr::Lit(Lit::Num(Number {
                                                                    span: DUMMY_SP,
                                                                    value: 58.0,
                                                                    raw: None,
                                                                }))),
                                                            }],
                                                            type_args:None,
                                                        })),
                                                    })),
                                                    prop: MemberProp::Ident(quote_ident!("fork")),
                                                }))),
                                                args: vec![],
                                                type_args:None,
                                            })),
                                        }),
                                        // if (scoresedRecord[key]) {...}
                                        Stmt::If(IfStmt {
                                            span: DUMMY_SP,
                                            test: Box::new(Expr::Paren(ParenExpr {
                                                span: DUMMY_SP,
                                                expr: Box::new(Expr::Member(MemberExpr {
                                                    span: DUMMY_SP,
                                                    obj: Box::new(Expr::Ident(record_ident.clone())),
                                                    prop: MemberProp::Computed(ComputedPropName {
                                                        span: DUMMY_SP,
                                                        expr: Box::new(Expr::Ident(quote_ident!("key"))),
                                                    }),
                                                })),
                                            })),
                                            cons: Box::new(Stmt::Block(BlockStmt {
                                                span: DUMMY_SP,
                                                stmts: vec![
                                                    // const value = (scoresedRecord[key] as number)
                                                    Stmt::Decl(Decl::Var(Box::new(VarDecl {
                                                        span: DUMMY_SP,
                                                        kind: VarDeclKind::Const,
                                                        decls: vec![VarDeclarator {
                                                            span: DUMMY_SP,
                                                            name: Pat::Ident(quote_ident!("value").into()),
                                                            init: Some(Box::new(Expr::Paren(ParenExpr {
                                                                span: DUMMY_SP,
                                                                expr: Box::new(Expr::TsAs(TsAsExpr {
                                                                    span: DUMMY_SP,
                                                                    expr: Box::new(Expr::Paren(ParenExpr {
                                                                        span: DUMMY_SP,
                                                                        expr: Box::new(Expr::Member(MemberExpr {
                                                                            span: DUMMY_SP,
                                                                            obj: Box::new(Expr::Ident(record_ident.clone())),
                                                                            prop: MemberProp::Computed(ComputedPropName {
                                                                                span: DUMMY_SP,
                                                                                expr: Box::new(Expr::Ident(quote_ident!("key"))),
                                                                            }),
                                                                        })),
                                                                    })),
                                                                    type_ann: Box::new(TsType::TsKeywordType(TsKeywordType {
                                                                        span: DUMMY_SP,
                                                                        kind: TsKeywordTypeKind::TsNumberKeyword,
                                                                    })),
                                                                })),
                                                            }))),
                                                            definite: false,
                                                        }],
                                                        declare: false,
                                                    }))),
                                                    // (($writer.uint32(10)).string_(key)
                                                    Stmt::Expr(ExprStmt {
                                                        span: DUMMY_SP,
                                                        expr: Box::new(Expr::Call(CallExpr {
                                                            span: DUMMY_SP,
                                                            callee: Callee::Expr(Box::new(Expr::Member(MemberExpr {
                                                                span: DUMMY_SP,
                                                                obj: Box::new(Expr::Paren(ParenExpr {
                                                                    span: DUMMY_SP,
                                                                    expr: Box::new(Expr::Call(CallExpr {
                                                                        span: DUMMY_SP,
                                                                        callee: Callee::Expr(Box::new(Expr::Member(MemberExpr {
                                                                            span: DUMMY_SP,
                                                                            obj: Box::new(Expr::Ident(quote_ident!("$writer"))),
                                                                            prop: MemberProp::Ident(quote_ident!("uint32")),
                                                                        }))),
                                                                        args: vec![ExprOrSpread {
                                                                            spread: None,
                                                                            expr: Box::new(Expr::Lit(Lit::Num(Number {
                                                                                span: DUMMY_SP,
                                                                                value: 10.0,
                                                                                raw: None,
                                                                            }))),
                                                                        }],
                                                                        type_args:None,
                                                                    })),
                                                                })),
                                                                prop: MemberProp::Ident(quote_ident!("string_")),
                                                            }))),
                                                            args: vec![ExprOrSpread {
                                                                spread: None,
                                                                expr: Box::new(Expr::Ident(quote_ident!("key"))),
                                                            }],
                                                            type_args:None,
                                                        })),
                                                    }),
                                                    // (($writer.uint32(16)).int32(value))
                                                    Stmt::Expr(ExprStmt {
                                                        span: DUMMY_SP,
                                                        expr: Box::new(Expr::Call(CallExpr {
                                                            span: DUMMY_SP,
                                                            callee: Callee::Expr(Box::new(Expr::Member(MemberExpr {
                                                                span: DUMMY_SP,
                                                                obj: Box::new(Expr::Paren(ParenExpr {
                                                                    span: DUMMY_SP,
                                                                    expr: Box::new(Expr::Call(CallExpr {
                                                                        span: DUMMY_SP,
                                                                        callee: Callee::Expr(Box::new(Expr::Member(MemberExpr {
                                                                            span: DUMMY_SP,
                                                                            obj: Box::new(Expr::Ident(quote_ident!("$writer"))),
                                                                            prop: MemberProp::Ident(quote_ident!("uint32")),
                                                                        }))),
                                                                        args: vec![ExprOrSpread {
                                                                            spread: None,
                                                                            expr: Box::new(Expr::Lit(Lit::Num(Number {
                                                                                span: DUMMY_SP,
                                                                                value: 16.0,
                                                                                raw: None,
                                                                            }))),
                                                                        }],
                                                                        type_args:None,
                                                                    })),
                                                                })),
                                                                prop: MemberProp::Ident(quote_ident!("int32")),
                                                            }))),
                                                            args: vec![ExprOrSpread {
                                                                spread: None,
                                                                expr: Box::new(Expr::Ident(quote_ident!("value"))),
                                                            }],
                                                            type_args:None,
                                                        })),
                                                    }),
                                                    // $writer.ldelim()
                                                    Stmt::Expr(ExprStmt {
                                                        span: DUMMY_SP,
                                                        expr: Box::new(Expr::Call(CallExpr {
                                                            span: DUMMY_SP,
                                                            callee: Callee::Expr(Box::new(Expr::Member(MemberExpr {
                                                                span: DUMMY_SP,
                                                                obj: Box::new(Expr::Ident(quote_ident!("$writer"))),
                                                                prop: MemberProp::Ident(quote_ident!("ldelim_")),
                                                            }))),
                                                            args: vec![],
                                                            type_args:None,
                                                        })),
                                                    }),
                                                ],
                                            })),
                                            alt: None,
                                        }),
                                    ],
                                })),
                                is_async: false,
                                is_generator: false,
                                type_params: None,
                                return_type: None,
                            })),
                        }],
                        type_args: None,
                    })),
                }),
            ],
        };
    
        // 生成完整的 if 语句
        Stmt::If(IfStmt {
            span: DUMMY_SP,
            test: Box::new(Expr::Member(MemberExpr {
                span: DUMMY_SP,
                obj: Box::new(host),
                prop: MemberProp::Ident(entry_ident),
            })),
            cons: Box::new(Stmt::Block(if_block)),
            alt: None,
        })
    }

pub fn serialize_primitive_field_stmt(
    &self,
    _ctx: &mut Context,
    host: Expr,
    field: &descriptor::FieldDescriptorProto,
    field_accessor: FieldAccessor,
    access_normalizer: Option<field::AccessNormalizerFn>,
    has_computed_prop: Option<bool>,
) -> Stmt {
    let has_computed_prop = has_computed_prop.unwrap_or(field.has_computed_prop());
    let access_expr = field_accessor(host, field, has_computed_prop);
    let access_expr = access_normalizer
        .map(|f| f(&access_expr))
        .unwrap_or_else(|| access_expr.clone());

    // 使用 pure_type_annotation 获取纯类型
    let typed_access_expr = if let Some(type_ann) = field.pure_type_annotation(_ctx) {
        Expr::TsAs(TsAsExpr {
            span: DUMMY_SP,
            expr: Box::new(access_expr.clone()),
            type_ann: Box::new(*type_ann.type_ann),  // 解引用获取 TsType
        })
    } else {
        // 回退到原来的硬编码类型匹配
        match field.type_() {
            Type::TYPE_STRING => Expr::TsAs(TsAsExpr {
                span: DUMMY_SP,
                expr: Box::new(access_expr.clone()),
                type_ann: Box::new(TsType::TsKeywordType(TsKeywordType {
                    span: DUMMY_SP,
                    kind: TsKeywordTypeKind::TsStringKeyword,
                })),
            }),
            
            _ => access_expr.clone(),
        }
    };

    // $w.uint32(/* id + wireType */)
    let id_write_expr = Expr::Call(CallExpr {
        span: DUMMY_SP,
        callee: Callee::Expr(Box::new(Expr::Member(MemberExpr {
            span: DUMMY_SP,
            obj: Box::new(Expr::Ident(Ident::new("$writer".into(), DUMMY_SP))),
            prop: MemberProp::Ident(Ident::new("uint32_".into(), DUMMY_SP)),
        }))),
        args: vec![ExprOrSpread {
            spread: None,
            expr: Box::new(Expr::Lit(Lit::Num(Number {
                span: DUMMY_SP,
                value: field.field_header().value() as f64,
                raw: None,
            }))),
        }],
        type_args: None,
    });

    let if_stmt = Stmt::If(IfStmt {
        span: DUMMY_SP,
        test: Box::new(access_expr),
        cons: Box::new(Stmt::Block(BlockStmt {
            span: DUMMY_SP,
            stmts: vec![
                Stmt::Expr(ExprStmt {
                    span: DUMMY_SP,
                    expr: Box::new(Expr::Call(CallExpr {
                        span: DUMMY_SP,
                        callee: Callee::Expr(Box::new(Expr::Member(MemberExpr {
                            span: DUMMY_SP,
                            obj: Box::new(id_write_expr),
                            prop: MemberProp::Ident(Ident::new(
                                (self.codec_fn_name(field)).as_str().into(),
                                DUMMY_SP
                            )),
                        }))),
                        args: vec![ExprOrSpread {
                            spread: None,
                            expr: Box::new(typed_access_expr),
                        }],
                        type_args: None,
                    })),
                })
            ],
        })),
        alt: None,
    });
    if_stmt
}


pub fn serialize_oneof_primitive_field_stmt(
        &self,
        _ctx: &mut Context,
        host: Expr,
        field: &descriptor::FieldDescriptorProto,
        field_accessor: FieldAccessor,
        access_normalizer: Option<field::AccessNormalizerFn>,
        has_computed_prop: Option<bool>,
    ) -> Stmt {
        let has_computed_prop = has_computed_prop.unwrap_or(field.has_computed_prop());
        eprintln!("[DEBUG] field_type has_computed_prop >>>>>>>>>>>>>>>>>>>>>>>>>> ==== {:?}", has_computed_prop);
        let access_expr = field_accessor(host.clone(), field, has_computed_prop);
        eprintln!("[DEBUG] field_type host >>>>>>>>>>>>>>>>>>>>>>>>>> ==== {:?}", host);
        eprintln!("[DEBUG] field_type field >>>>>>>>>>>>>>>>>>>>>>>>>> ==== {:?}", field);
        eprintln!("[DEBUG] field_type access_expr111 >>>>>>>>>>>>>>>>>>>>>>>>>> ==== {:?}", access_expr);
        let access_expr = access_normalizer
            .map(|f| f(&access_expr))
            .unwrap_or(access_expr);
        eprintln!("[DEBUG] field_type access_expr222 >>>>>>>>>>>>>>>>>>>>>>>>>> ==== {:?}", access_expr);
        // $w.uint32(/* id + wireType */)
        let id_write_expr = crate::call_expr!(
            crate::member_expr!("$writer", "uint32"),
            vec![crate::expr_or_spread!(
                crate::lit_num!(field.field_header().value()).into()
            )]
        );
        eprintln!("[DEBUG] field_type id_write_expr >>>>>>>>>>>>>>>>>>>>>>>>>> ==== {:?}", id_write_expr);
        eprintln!("[DEBUG] field_type id_write_expr2222 >>>>>>>>>>>>>>>>>>>>>>>>>> ==== {:?}", crate::expr_stmt!(crate::call_expr!(
            crate::member_expr_bare!(id_write_expr.clone(), self.codec_fn_name(field)),
            vec![crate::expr_or_spread!(access_expr.clone())]
        )));
        // $w.uint32(/* */).xxx(/* */)
        crate::expr_stmt!(crate::call_expr!(
            crate::member_expr_bare!(id_write_expr, self.codec_fn_name(field)),
            vec![crate::expr_or_spread!(access_expr)]
        ))
    }

    // pub fn serialize_primitive_field_stmt(
    //     &self,
    //     _ctx: &mut Context,
    //     host: Expr,
    //     field: &descriptor::FieldDescriptorProto,
    //     field_accessor: FieldAccessor,
    //     access_normalizer: Option<field::AccessNormalizerFn>,
    //     has_computed_prop: Option<bool>,
    // ) -> Stmt {
    //     let has_computed_prop = has_computed_prop.unwrap_or(field.has_computed_prop());
    //     eprintln!("[DEBUG] field_type has_computed_prop >>>>>>>>>>>>>>>>>>>>>>>>>> ==== {:?}", has_computed_prop);
    //     let access_expr = field_accessor(host, field, has_computed_prop);
    //     eprintln!("[DEBUG] field_type access_expr111 >>>>>>>>>>>>>>>>>>>>>>>>>> ==== {:?}", access_expr);
    //     let access_expr = access_normalizer
    //         .map(|f| f(&access_expr))
    //         .unwrap_or(access_expr);
    //     eprintln!("[DEBUG] field_type access_expr222 >>>>>>>>>>>>>>>>>>>>>>>>>> ==== {:?}", access_expr);
    //     // $w.uint32(/* id + wireType */)
    //     let id_write_expr = crate::call_expr!(
    //         crate::member_expr!("$writer", "uint32"),
    //         vec![crate::expr_or_spread!(
    //             crate::lit_num!(field.field_header().value()).into()
    //         )]
    //     );
    //     eprintln!("[DEBUG] field_type id_write_expr >>>>>>>>>>>>>>>>>>>>>>>>>> ==== {:?}", id_write_expr);
    //     eprintln!("[DEBUG] field_type id_write_expr2222 >>>>>>>>>>>>>>>>>>>>>>>>>> ==== {:?}", crate::expr_stmt!(crate::call_expr!(
    //         crate::member_expr_bare!(id_write_expr.clone(), self.codec_fn_name(field)),
    //         vec![crate::expr_or_spread!(access_expr.clone())]
    //     )));
    //     // $w.uint32(/* */).xxx(/* */)
    //     crate::expr_stmt!(crate::call_expr!(
    //         crate::member_expr_bare!(id_write_expr, self.codec_fn_name(field)),
    //         vec![crate::expr_or_spread!(access_expr)]
    //     ))
    // }
}
